package top.todu.demo.spirngcloud.gateway.demo.config;

import java.nio.charset.StandardCharsets;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.Ordered;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

/** filter 名字为前缀 ，也就是 TcpService， GatewayFilterFactory 是固定后缀 */
@Component
@Slf4j
public class TcpServiceGatewayFilterFactory
    extends AbstractGatewayFilterFactory<TcpServiceGatewayFilterFactory.Config> implements Ordered {

  public TcpServiceGatewayFilterFactory() {
    super(Config.class);
  }

  @Override
  public GatewayFilter apply(Config config) {
    return (exchange, chain) -> {
      log.info("自定义：1, isCommitted: {}", exchange.getResponse().isCommitted());
      exchange.getAttributes().put("targetSchema", "tcp");
      // 处理TCP服务的逻辑
      String host = config.getHost();
      int port = config.getPort();
      // 建立到TCP服务的连接,并发送请求数据
      byte[] requestData = "从exchange中获取请求数据".getBytes(StandardCharsets.UTF_8); // 从exchange中获取请求数据
      byte[] responseData = "从TCP服务中获取响应数据".getBytes(StandardCharsets.UTF_8); // 从TCP服务中获取响应数据
      // 将响应数据写回到exchange中
      // 将响应数据写回到exchange中
      ServerHttpResponse response = exchange.getResponse();
      response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
      Mono<Void> voidMono = response.writeWith(Mono.just(response.bufferFactory().wrap(responseData)));
      log.info("自定义：1, isCommitted: {}", exchange.getResponse().isCommitted());
      return voidMono.then(chain.filter(exchange));
    };
  }

  @Override
  public int getOrder() {
    return Ordered.LOWEST_PRECEDENCE;
  }

  public static class Config {
    private String host;
    private int port;

    public String getHost() {
      return host;
    }

    public void setHost(String host) {
      this.host = host;
    }

    public int getPort() {
      return port;
    }

    public void setPort(int port) {
      this.port = port;
    }
  }
}
